// 1. useDrag
import type { App } from "vue";
import { throttle } from "./register";

interface IuseDrag {
  (el: HTMLElement, cb?: (e: MouseEvent) => void): void;
  install: (app: App, name: string) => void;
}

export const useDrag: IuseDrag = (el, callback) => {
  const diff = { x: 0, y: 0 };

  const onMouseMove = (e: MouseEvent) => {
    el.style.left = `${e.clientX - diff.x}px`;
    el.style.top = `${e.clientY - diff.y}px`;
    callback && callback(e);
  };

  const onMouseUp = () => {
    document.removeEventListener("mousemove", onMouseMove);
    document.removeEventListener("mouseup", onMouseUp);
  };

  const onMouseDown = (e: MouseEvent) => {
    e.preventDefault();
    diff.x = e.clientX - el.offsetLeft;
    diff.y = e.clientY - el.offsetTop;

    // 拖拽事件在 document 上，保证鼠标不会脱离原始
    document.addEventListener("mousemove", onMouseMove, { passive: true });
    document.addEventListener("mouseup", onMouseUp, { passive: true });
  };

  // mousedown 事件在目标元素上，保证仅点击目标元素才会拖拽
  el.addEventListener("mousedown", onMouseDown);
};

useDrag.install = (app, directiveName = "drag") => {
  app.directive(directiveName, {
    mounted(el, binding) {
      const onDrag = (e: MouseEvent) => {
        const { value } = binding;
        if (value) {
          value(e);
        }
      };
      useDrag(el, throttle(onDrag, 200));
    },
  });
  return app
};

export default useDrag;
